// //判断数据类型
// function checkedType(target) {
//     return Object.prototype.toString.call(target).slice(8, -1);
// }


// console.log(checkedType([])); // "Array"
// console.log(checkedType({})); // "Object"
// console.log(checkedType(null)); // "Null"
// console.log(checkedType(undefined)); // "Undefined"

//-------------------------------------------------------------------------------
// // 实现深度克隆---对象/数组
// function deepCopy(target) {
//     var result; // 初始化变量result 成为最终克隆的数据
//     var targetType = checkedType(target); // 判断拷贝的数据类型
//     if (targetType === 'Object') {
//         result = {};
//     } else if (targetType === 'Array') {
//         result = [];
//     } else {
//         return target;
//     }
//     // 遍历目标数据
//     for (let key in target) {
//         // 获取遍历数据结构的每一项值。
//         let value = target[key];
//         // 判断目标结构里的每一值是否存在对象/数组
//         if (checkedType(value) === 'Object' || checkedType(value) === 'Array') {
//             // 继续递归遍历获取到value值
//             result[key] = deepCopy(value);
//         } else {
//             // 获取到value值是基本的数据类型或者是函数。
//             result[key] = value;
//         }
//     }
//     return result;
// }


// var obj1 = {
//     'name': 'zhangsan',
//     'age': 18,
//     'language': [1, [2, 3],
//         [4, 5]
//     ]
// };

// var obj2 = deepCopy(obj1);
// obj2.name = "lisi";
// obj2.language[1] = ["二", "三"];


// console.log('obj1', obj1); // {name: "zhangsan", age: 18, language: [1, [2, 3], [4, 5]]}
// console.log('obj2', obj2); // {name: "lisi", age: 18, language: [1, ["二", "三"], [4, 5]]}

//---------------------------------------------------------------------------------------------------------
// 判断obj是否为对象或数组
// function isObject(obj) {
// 	return (typeof obj === 'object' && obj !== null);
// }

// 全相等函数
// function isEqual(obj1, obj2) {
// 	if (!isObject(obj1) || !isObject(obj2)) {
// 		return obj1 === obj2
// 	}

// 	if (obj1 === obj2) {
// 		return true
// 	}

// 	if (Object.keys(obj1).length !== Object.keys(obj2).length) {
// 		return false
// 	}

// 	for (const key in obj1) {
// 		let res = isEqual(obj1[key], obj2[key]);
// 		if (!res) {
// 			return false
// 		}
// 	}
// 	return true
// }


// const obj1 = {
// 	a: 1,
// 	b: {
// 		x: 'aa',
// 		y: 'bb',
// 		z: 'cc'
// 	},
// 	c: [1, 2, 3]
// }

// const obj2 = {
// 	a: 1,
// 	b: {
// 		x: 'aa',
// 		y: 'bb',
// 		z: 'cc'
// 	},
// 	c: [1, 2, 3]
// }


// console.log(isEqual(obj1, obj2)); // true

//-------------------------------------------------------------------------------------------------
防抖
function debounce(fn,delay) {
    let timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this,arguments);
        },delay);
    }
}

//------------------------------------------------------------------------
//节流
// function throttle(fn, delay) {
// 	let flag = true;
// 	return function () {
// 		if (!flag) { return; }
// 		flag = false;
// 		setTimeout(() => {
// 			fn.apply(this, arguments);
// 			flag = true;
// 		}, delay);
// 	}
// }

//---------------------------------------------------------------------
//数组扁平化
// function flatten(arr) {
//     var res = [];
//     arr.map(item => {
//         if (Array.isArray(item)) {
//             res = res.concat(flatten(item));
//         } else {
//             res.push(item);
//         }
//     });
//     return res;
// }

// var arr = [[1, 2], 3, [4, 5, [6, 7, [8, 9, [10, 11]]]]]; // 多维数组

// console.log(flatten(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

//-----------------------------------------------------------------------------------------
//数组去重
// let arr = [1, 2, 2, 3, 'x', 4, 3, 2, 1, 'x'];

// // 方法一：利用filter
// function unique1(arr) {
// 	return arr.filter((item, index, self) => {
// 		return self.indexOf(item) == index
// 	})
// }

// // 方法二：利用Set
// function unique2(arr) {
// 	return [...new Set(arr)];
// 	// 或
// 	//return Array.from(new Set(arr));
// }

// // 方法三：利用for循环
// function unique3 (arr) {
//   let result = []; 
//   for (var i = 0; i < arr.length; i++) {
//     if (result.indexOf(arr[i]) == -1) result.push(arr[i]);
//   }
//   return result;
// }

//---------------------------------------------------------------------
//new
// function _new(func, ...args) {
//     // 1. 创建空对象
//     let obj = {};
//     // 2. 空对象的_proto_指向了构造函数的prototype成员对象
//     obj.__proto__ = func.prototype; // 1、2步合并就相当于 let obj = Object.create(func.prototype)
//     // 3. 使用apply调用构造器函数，属性和方法被添加到 this 引用的对象中
//     let result = func.apply(obj, args);
// 	// 4. 确保 new 出来的是个对象
//     return typeof result === 'object' ? result : obj;
// }


// function Person(name, age) {
//   this.name = name;
//   this.age = age;
// }

// let obj = _new(Person, 'xia', 20);

// console.log(obj); //{name: 'xia', age: 20}

//---------------------------------------------------------------------------------
//Ajax
// function _ajax() {
//     // 1.创建XMLHttpRequest对象
//     var ajax = new XMLHttpRequest();

//     // 2.绑定监听事件
//     ajax.onreadystatechange = function () {
//         // 当异步请求状态变为4时，并且返回的状态码为200，接收响应成功
//         if (ajax.readyState == 4 && ajax.status == 200) {
//             // 如果能够进到这里，说明数据完美的回来了,并且请求的页面是存在的
//             console.log(ajax.responseText); // 输入相应的内容
//         }
//     };

//     // 3.调用open方法传入三个参数：请求方式(GET/POST)、url、同步异步(true/false);
//     ajax.open('get', 'getStar.php?starName=' + name);

//     // 4.发送请求，不带参数为GET请求
//     ajax.send();
// }

//---------------------------------------------------------------------------------
//Promise.all
// Promise.MyAll = function (promises) {
//     let arr = []
//     count = 0
//     return new Promise((resolve, reject) => {
//         promises.forEach((item, i) => {
//             Promise.resolve(item).then(res => {
//                 arr[i] = res
//                 count += 1
//                 if (count === promises.length) {
//                     resolve(arr)
//                 }
//             },reject)
//         })
//     })
// }

//---------------------------------------------------------------------------------
//Promise.race
// Promise.MyRace = function(promises) {
//     return new Promise((resolve, reject) => {
//         for(const item of promises) {
//             Promise.resolve(item).then(resolve, reject)
//         }
//     })
// }

//---------------------------------------------------------------------------------
//call()
// Function.prototype.myCall = function (thisArg, ...args) {
//     thisArg = thisArg ? Object(thisArg) : window
//     thisArg.fn = this
//     let result = thisArg.fn(...args)
//     delete thisArg.fn
//     return result
// }


// function curry(func) { 
//     return function curried(...args) {    
//       if (args.length >= func.length) {      
//         return func.apply(this, args);    } 
//       else {      
//         return function(...args2) { 
//           return curried.apply(this, args.concat(args2));      
//           }   
//       } 
//     };
// }


// function sum(a, b, c) {  
//     return a + b + c;}
//   let curriedSum = curry(sum);
//   console.log( curriedSum(1, 2, 3) ); // 6，仍然可以被正常调用
//   console.log( curriedSum(1)(2,3) ); // 6，对第一个参数的柯里化
//   console.log( curriedSum(1)(2)(3) ); // 6，全柯里化

// function flatten(arr) {
//   let result = [];
//   for(let i = 0; i < arr.length; i++) {
//     if(Array.isArray(arr[i])) {
//       result = result.concat( flatten(arr[i]))
//     } else {
//       result.push(arr[i])
//     }
//   }
//   return result
// }

// function flatten2(arr) {
//   return arr.reduce(function (prev, next) {
//     return prev.concat(Array.isArray(next) ? flatten(next) : next)
//   },[])
// }

// let result = arr.flat(Infinity)
// let result2 = flatten(arr)

let name="张三",age="18";
let desc="${name} 今年  ${age}  岁了";
function replace(desc){
    return desc.replace(/\$\{([^}]+)\}/g,function(mathed,key,c,d){
            console.log(mathed,key,c,d)
            //${name} name 0 ${name} 今年  ${age}  岁了
            //${age} age 12 ${name} 今年  ${age}  岁了
            //replace中 mathed 为匹配到的字符串，key为对应替换的字符串，c为替换的位置，d为整个要替换的字符串。
            return eval(key);
            //eval() 函数可计算某个字符串，并执行其中的的 JavaScript 代码。这里的eval会将原本的name和age改成成张三和18
    })
}
console.log(replace(desc));